/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package tools;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import main.Bot;
import main.Main;

import org.apache.log4j.Logger;

import database.DBConnectionFactory;
import exceptions.UtoDateException;

/**
 * This class provides conversion and comparisons between real time and utopia time
 * 
 * 
 */
public class UtopiaTime {
   /**
    * Compares the supplied time to the current time
    * 
    * @param time
    * @return
    */
   public static String compareTimes(final Long time) {
	  Long remains = time - Calendar.getInstance().getTimeInMillis();
	  if (remains < 0) {
		 remains = Calendar.getInstance().getTimeInMillis() - time;
	  }
	  remains = remains / 1000;
	  final Long hours = remains / 3600;
	  final Long mins = remains % 3600 / 60;
	  final Long secs = remains % 3600 % 60;

	  String temp = "";
	  if (hours > 0) {
		 temp += hours + "h, ";
	  }
	  if (mins > 0) {
		 temp += mins + "m, ";
	  }
	  if (secs > 0) {
		 temp += secs + "s";
	  }
	  if (temp.endsWith(", ")) {
		 temp = temp.substring(0, temp.length() - 2);
	  }
	  return temp;
   }

   /**
    * Sets the start of the age
    * 
    * @param currentUtoDate
    * @param bot
    * @return
    */
   public static boolean setStartDate(final String currentUtoDate, final Bot bot) {
	  boolean out = false;
	  final String[] temp = currentUtoDate.replace(" of", "").split(" ");

	  int month;
	  if (temp[0].equalsIgnoreCase("January")) {
		 month = 0;
	  } else if (temp[0].equalsIgnoreCase("February")) {
		 month = 1;
	  } else if (temp[0].equalsIgnoreCase("March")) {
		 month = 2;
	  } else if (temp[0].equalsIgnoreCase("April")) {
		 month = 3;
	  } else if (temp[0].equalsIgnoreCase("May")) {
		 month = 4;
	  } else if (temp[0].equalsIgnoreCase("June")) {
		 month = 5;
	  } else {
		 month = 6;
	  }

	  final int day = Integer.parseInt(temp[1].replaceAll("[^0-9]", "")) - 1;

	  final int year = Integer.parseInt(temp[2].replaceAll("[^0-9]", ""));

	  GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
	  cal.setTimeZone(TimeZone.getTimeZone("GMT"));
	  cal.add(Calendar.HOUR_OF_DAY, -day);
	  cal.add(Calendar.DAY_OF_YEAR, -month);
	  cal.add(Calendar.WEEK_OF_YEAR, -year);
	  cal.setTimeInMillis(cal.getTimeInMillis() - cal.getTimeInMillis() % (Main.getBotSettings().getTickLength() * 60L * 1000));

	  PreparedStatement ps = null;
	  try {
		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("UPDATE settings SET agestart = ?");
		 ps.setTimestamp(1, new Timestamp(cal.getTimeInMillis()));
		 if (ps.executeUpdate() == 1) {
			Main.getBotSettings().setAgeStart(cal.getTimeInMillis());
			out = true;
		 }
	  } catch (SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			ps.close();
		 } catch (Exception e) {
		 }
	  }
	  return out;
   }

   private final Long utyear;
   private String utmonth;

   private final String utday;

   private final Long time;

   public UtopiaTime(final Long time) {
	  Long temp = Long.valueOf(0L);
	  temp = time - Main.getBotSettings().getAgeStart();

	  this.time = time;

	  temp = temp / 1000;
	  utyear = Math.max(temp / (7L * 24 * Main.getBotSettings().getTickLength() * 60), 0);
	  final Long month = temp % (7L * 24 * Main.getBotSettings().getTickLength() * 60)
			/ (24L * Main.getBotSettings().getTickLength() * 60);
	  if (month <= 0) {
		 utmonth = "January";
	  } else if (month == 1) {
		 utmonth = "February";
	  } else if (month == 2) {
		 utmonth = "March";
	  } else if (month == 3) {
		 utmonth = "April";
	  } else if (month == 4) {
		 utmonth = "May";
	  } else if (month == 5) {
		 utmonth = "June";
	  } else if (month == 6) {
		 utmonth = "July";
	  }
	  final Long day = Math.max(temp % (7 * 24 * Main.getBotSettings().getTickLength() * 60L)
			% (24 * Main.getBotSettings().getTickLength() * 60L) / (Main.getBotSettings().getTickLength() * 60L) + 1, 1L);
	  String d = "";
	  if (day == 1 || day == 21) {
		 d = "st";
	  } else if (day == 2 || day == 22) {
		 d = "nd";
	  } else if (day == 3 || day == 23) {
		 d = "rd";
	  } else {
		 d = "th";
	  }
	  utday = day + d;
   }

   public UtopiaTime(final String uttime) throws UtoDateException {
	  if (!StringTools.validateInput(InputType.UTODATE, uttime))
		 throw new UtoDateException();

	  final String[] temp = uttime.replace(" of", "").split(" ");

	  Long month;
	  if (temp[0].equalsIgnoreCase("January")) {
		 month = Long.parseLong("0");
	  } else if (temp[0].equalsIgnoreCase("February")) {
		 month = Long.parseLong("1");
	  } else if (temp[0].equalsIgnoreCase("March")) {
		 month = Long.parseLong("2");
	  } else if (temp[0].equalsIgnoreCase("April")) {
		 month = Long.parseLong("3");
	  } else if (temp[0].equalsIgnoreCase("May")) {
		 month = Long.parseLong("4");
	  } else if (temp[0].equalsIgnoreCase("June")) {
		 month = Long.parseLong("5");
	  } else {
		 month = Long.parseLong("6");
	  }

	  final Long day = Long.parseLong(temp[1].replaceAll("[^0-9]", ""));

	  final Long year = Long.parseLong(temp[2].replaceAll("[^0-9]", ""));

	  time = (year * 7 * 24 * Main.getBotSettings().getTickLength() * 60 + month * 24 * Main.getBotSettings().getTickLength()
			* 60 + (day - 1) * Main.getBotSettings().getTickLength() * 60)
			* 1000 + Main.getBotSettings().getAgeStart();
	  utyear = year;
	  utmonth = temp[0];
	  String d = "";
	  if (day == 1 || day == 21) {
		 d = "st";
	  } else if (day == 2 || day == 22) {
		 d = "nd";
	  } else if (day == 3 || day == 23) {
		 d = "rd";
	  } else {
		 d = "th";
	  }
	  utday = day + d;
   }

   /**
    * Returns a formatted uto date
    * 
    * @return
    */
   public String formattedUT() {
	  return utmonth + " " + utday + ", YR" + utyear;
   }

   public String getDay() {
	  return utday;
   }

   /**
    * Returns a future uto date
    * 
    * @param ticks
    * @return
    */
   public String getFutureDate(final Double ticks) {
	  Double temp = ticks * Main.getBotSettings().getTickLength() * 60 * 1000 + time;
	  return new UtopiaTime(temp.longValue()).formattedUT();
   }

   public String getMonth() {
	  return utmonth;
   }

   public Long getTime() {
	  return time;
   }

   public Long getYear() {
	  return utyear;
   }
}
